<template>
  <n-modal
    v-model:show="visible"
    :mask-closable="false"
    :close-on-esc="true"
    preset="card"
    :style="modalStyle"
    :content-style="contentStyle"
    :header-style="headerStyle"
    size="huge"
    :bordered="false"
    @update:show="handleClose"
  >
    <template #header>
      <div class="modal-header">
        <span class="modal-title">文本对比结果</span>
        <div class="header-legend">
          <n-space :size="16">
            <div class="legend-item">
              <div class="legend-color unchanged"></div>
              <span>相同</span>
            </div>
            <div class="legend-item">
              <div class="legend-color modified"></div>
              <span>修改</span>
            </div>
            <div class="legend-item">
              <div class="legend-color added"></div>
              <span>新增</span>
            </div>
            <div class="legend-item">
              <div class="legend-color deleted"></div>
              <span>删除</span>
            </div>
          </n-space>
        </div>
      </div>
    </template>
    
    <template #header-extra>
      <n-space>
        <n-button
          v-if="result"
          type="primary"
          size="small"
          @click="handleCopyDiff"
        >
          复制差异
        </n-button>
        <n-button
          size="small"
          @click="handleClose"
        >
          关闭
        </n-button>
      </n-space>
    </template>

    <div v-if="loading" class="loading-container">
      <n-spin size="large" />
      <n-text>正在对比文本...</n-text>
    </div>

    <div v-else-if="result" class="comparison-content">
      <!-- 对比摘要 -->
      <n-card title="对比摘要" :bordered="false" class="summary-card">
        <n-grid :cols="24" :x-gap="16" :y-gap="16">
          <n-gi :span="isMobile ? 12 : 6">
            <n-statistic label="相似度" :value="(result.similarity * 100).toFixed(1)" suffix="%" />
          </n-gi>
          <n-gi :span="isMobile ? 12 : 6">
            <n-statistic label="新增行" :value="result.addedLines" />
          </n-gi>
          <n-gi :span="isMobile ? 12 : 6">
            <n-statistic label="删除行" :value="result.deletedLines" />
          </n-gi>
          <n-gi :span="isMobile ? 12 : 6">
            <n-statistic label="处理耗时" :value="result.elapsedTime" suffix="ms" />
          </n-gi>
        </n-grid>
        
        <!-- 详细统计信息 -->
        <n-collapse style="margin-top: 16px">
          <n-collapse-item title="详细统计信息" name="stats">
            <n-grid :cols="24" :x-gap="16" :y-gap="16">
              <n-gi :span="24">
                <n-space vertical>
                  <div class="stat-section">
                    <div class="stat-title">行统计</div>
                    <n-space>
                      <n-tag type="info">总行数: {{ result.detailedStatistics.lineStatistics.totalLines }}</n-tag>
                      <n-tag type="success">相同: {{ result.detailedStatistics.lineStatistics.sameLines }}行</n-tag>
                      <n-tag type="warning" v-if="result.detailedStatistics.lineStatistics.modifiedLines > 0">修改: {{ result.detailedStatistics.lineStatistics.modifiedLines }}行</n-tag>
                    </n-space>
                  </div>
                  
                  <div class="stat-section">
                    <div class="stat-title">字符统计</div>
                    <n-space>
                      <n-tag type="info">总字符: {{ result.detailedStatistics.characterStatistics.totalCharacters }}</n-tag>
                      <n-tag type="success">相同: {{ result.detailedStatistics.characterStatistics.sameCharacters }}</n-tag>
                      <n-tag type="warning" v-if="result.detailedStatistics.characterStatistics.differentCharacters > 0">不同: {{ result.detailedStatistics.characterStatistics.differentCharacters }}</n-tag>
                    </n-space>
                  </div>
                  
                  <div class="stat-section">
                    <div class="stat-title">字符分类</div>
                    <n-space>
                      <n-tag>中文: {{ result.detailedStatistics.netCharacterStatistics.chineseCharacters }}</n-tag>
                      <n-tag>英文: {{ result.detailedStatistics.netCharacterStatistics.englishCharacters }}</n-tag>
                      <n-tag>数字: {{ result.detailedStatistics.netCharacterStatistics.digitCharacters }}</n-tag>
                      <n-tag>标点: {{ result.detailedStatistics.netCharacterStatistics.punctuationCharacters }}</n-tag>
                    </n-space>
                  </div>
                </n-space>
              </n-gi>
            </n-grid>
          </n-collapse-item>
        </n-collapse>
      </n-card>

      <!-- 左右对比视图 -->
      <div class="comparison-view">
        <div class="view-header">
          <div class="view-title left">{{ text1Title }}</div>
          <div class="vs-divider">VS</div>
          <div class="view-title right">{{ text2Title }}</div>
        </div>

        <!-- 同步滚动的对比容器 -->
        <div class="diff-container" ref="diffContainer">
          <div class="diff-wrapper left" ref="leftDiff" @scroll="handleLeftScroll">
            <div class="diff-content">
              <div
                v-for="(line, index) in leftLines"
                :key="index"
                :class="['diff-line', getLineClass(line)]"
              >
                <div class="line-number">{{ line.lineNumber || '' }}</div>
                <div class="line-content" v-html="line.highlightedContent || escapeHtml(line.content)"></div>
              </div>
            </div>
          </div>

          <div class="diff-wrapper right" ref="rightDiff" @scroll="handleRightScroll">
            <div class="diff-content">
              <div
                v-for="(line, index) in rightLines"
                :key="index"
                :class="['diff-line', getLineClass(line)]"
              >
                <div class="line-number">{{ line.lineNumber || '' }}</div>
                <div class="line-content" v-html="line.highlightedContent || escapeHtml(line.content)"></div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </n-modal>
</template>

<script setup lang="ts">
import { ref, computed, nextTick, watch } from 'vue'
import { useMessage } from 'naive-ui'
import type { ComparisonResult, LineDiff, CharacterDifference } from '@/api/utility/textComparison'
import { useBreakpoint } from '@/utils/responsive-helper'

interface Props {
  modelValue: boolean
  result: ComparisonResult | null
  loading?: boolean
  text1Title?: string
  text2Title?: string
}

const props = withDefaults(defineProps<Props>(), {
  text1Title: '文本 1',
  text2Title: '文本 2'
})

const emit = defineEmits(['update:modelValue'])

const { isMobile } = useBreakpoint()
const message = useMessage()

const visible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

// 样式计算
const modalStyle = computed(() => ({
  position: 'fixed',
  top: '60px',
  left: '0',
  right: '0',
  bottom: '0',
  margin: '0',
  maxHeight: 'calc(100vh - 60px)',
  height: 'calc(100vh - 60px)',
  display: 'flex',
  flexDirection: 'column'
}))

const contentStyle = computed(() => ({
  height: '100%',
  display: 'flex',
  flexDirection: 'column',
  padding: isMobile.value ? '12px' : '20px'
}))

const headerStyle = computed(() => ({
  padding: isMobile.value ? '12px' : '16px 20px'
}))

// 同步滚动相关
const leftDiff = ref<HTMLElement>()
const rightDiff = ref<HTMLElement>()
let isScrolling = false

const handleLeftScroll = (e: Event) => {
  if (isScrolling || !rightDiff.value) return
  isScrolling = true
  const target = e.target as HTMLElement
  rightDiff.value.scrollTop = target.scrollTop
  rightDiff.value.scrollLeft = target.scrollLeft
  setTimeout(() => { isScrolling = false }, 10)
}

const handleRightScroll = (e: Event) => {
  if (isScrolling || !leftDiff.value) return
  isScrolling = true
  const target = e.target as HTMLElement
  leftDiff.value.scrollTop = target.scrollTop
  leftDiff.value.scrollLeft = target.scrollLeft
  setTimeout(() => { isScrolling = false }, 10)
}

// 处理行差异显示
interface DisplayLine {
  lineNumber?: number
  type: 'SAME' | 'ADDED' | 'DELETED' | 'MODIFIED' | 'EMPTY'
  content: string
  highlightedContent?: string
  characterDifferences?: CharacterDifference[]
}

// HTML 转义函数
const escapeHtml = (text: string): string => {
  const map: Record<string, string> = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  }
  return text.replace(/[&<>"']/g, m => map[m])
}

// 生成带有字符级别高亮的 HTML
const generateHighlightedContent = (
  content: string,
  characterDifferences: CharacterDifference[] | undefined,
  isLeftSide: boolean
): string => {
  if (!characterDifferences || characterDifferences.length === 0) {
    return escapeHtml(content)
  }

  // 收集所有需要高亮的片段
  const highlights: Array<{ start: number; end: number; type: 'DELETE' | 'INSERT' }> = []
  
  characterDifferences.forEach(diff => {
    if (isLeftSide && diff.type === 'DELETE' && diff.startPos1 !== undefined && diff.endPos1 !== undefined) {
      highlights.push({ start: diff.startPos1, end: diff.endPos1, type: 'DELETE' })
    } else if (!isLeftSide && diff.type === 'INSERT' && diff.startPos2 !== undefined && diff.endPos2 !== undefined) {
      highlights.push({ start: diff.startPos2, end: diff.endPos2, type: 'INSERT' })
    }
  })

  // 按位置排序
  highlights.sort((a, b) => a.start - b.start)

  // 构建 HTML
  let html = ''
  let lastEnd = 0

  highlights.forEach(highlight => {
    // 添加高亮前的普通文本
    if (highlight.start > lastEnd) {
      html += escapeHtml(content.substring(lastEnd, highlight.start))
    }
    
    // 添加高亮文本
    const highlightClass = highlight.type === 'DELETE' ? 'char-deleted' : 'char-inserted'
    html += `<span class="${highlightClass}">${escapeHtml(content.substring(highlight.start, highlight.end))}</span>`
    
    lastEnd = highlight.end
  })

  // 添加剩余的文本
  if (lastEnd < content.length) {
    html += escapeHtml(content.substring(lastEnd))
  }

  return html
}

const leftLines = computed<DisplayLine[]>(() => {
  if (!props.result) return []
  
  const lines: DisplayLine[] = []
  
  props.result.lineDiffs.forEach(diff => {
    if (diff.status === 'SAME' || diff.status === 'DELETED' || diff.status === 'MODIFIED') {
      const line: DisplayLine = {
        lineNumber: diff.lineNumber > 0 ? diff.lineNumber : undefined,
        type: diff.status,
        content: diff.content,
        characterDifferences: diff.characterDifferences
      }
      
      // 如果是 MODIFIED 状态，生成高亮内容
      if (diff.status === 'MODIFIED' && diff.characterDifferences) {
        line.highlightedContent = generateHighlightedContent(diff.content, diff.characterDifferences, true)
      }
      
      lines.push(line)
    } else if (diff.status === 'ADDED') {
      // 添加的行在左侧显示为空行
      lines.push({
        type: 'EMPTY',
        content: ''
      })
    }
  })
  
  return lines
})

const rightLines = computed<DisplayLine[]>(() => {
  if (!props.result) return []
  
  const lines: DisplayLine[] = []
  
  props.result.lineDiffs.forEach(diff => {
    if (diff.status === 'SAME' || diff.status === 'ADDED' || diff.status === 'MODIFIED') {
      // 对于 MODIFIED 状态，右侧应该显示 content2
      const content = diff.status === 'MODIFIED' && diff.content2 ? diff.content2 : diff.content
      
      const line: DisplayLine = {
        lineNumber: diff.lineNumber2 || (diff.lineNumber > 0 ? diff.lineNumber : undefined),
        type: diff.status,
        content: content,
        characterDifferences: diff.characterDifferences
      }
      
      // 如果是 MODIFIED 状态，生成高亮内容
      if (diff.status === 'MODIFIED' && diff.characterDifferences && diff.content2) {
        line.highlightedContent = generateHighlightedContent(diff.content2, diff.characterDifferences, false)
      }
      
      lines.push(line)
    } else if (diff.status === 'DELETED') {
      // 删除的行在右侧显示为空行
      lines.push({
        type: 'EMPTY',
        content: ''
      })
    }
  })
  
  return lines
})

// 获取行的样式类
const getLineClass = (line: DisplayLine) => {
  switch (line.type) {
    case 'SAME':
      return 'line-unchanged'
    case 'ADDED':
      return 'line-added'
    case 'DELETED':
      return 'line-deleted'
    case 'MODIFIED':
      return 'line-modified'
    case 'EMPTY':
      return 'line-empty'
    default:
      return ''
  }
}

const handleClose = () => {
  visible.value = false
}

const handleCopyDiff = () => {
  if (!props.result) return
  
  const diffText = props.result.lineDiffs
    .filter(line => line.status !== 'SAME')
    .map(line => {
      let prefix = ''
      if (line.status === 'ADDED') prefix = '+'
      else if (line.status === 'DELETED') prefix = '-'
      else if (line.status === 'MODIFIED') prefix = '~'
      return `${prefix} ${line.content}`
    })
    .join('\n')
  
  navigator.clipboard.writeText(diffText).then(() => {
    message.success('差异内容已复制到剪贴板')
  }).catch(() => {
    message.error('复制失败，请手动复制')
  })
}

// 监听显示状态，重置滚动位置
watch(visible, (newVal) => {
  if (newVal) {
    nextTick(() => {
      if (leftDiff.value) leftDiff.value.scrollTop = 0
      if (rightDiff.value) rightDiff.value.scrollTop = 0
    })
  }
})
</script>

<style scoped lang="less">
.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 400px;
  gap: 16px;
}

.comparison-content {
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.summary-card {
  flex-shrink: 0;
}

.stat-section {
  .stat-title {
    font-weight: 500;
    margin-bottom: 8px;
    color: var(--n-text-color2);
  }
}

.comparison-view {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.view-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0;
  border-bottom: 1px solid var(--n-border-color);
  flex-shrink: 0;
  
  .view-title {
    flex: 1;
    font-weight: 500;
    font-size: 16px;
    
    &.left {
      text-align: left;
    }
    
    &.right {
      text-align: right;
    }
  }
  
  .vs-divider {
    padding: 0 20px;
    font-weight: bold;
    color: var(--n-text-color3);
  }
}

.diff-container {
  flex: 1;
  display: flex;
  gap: 2px;
  min-height: 0;
  margin-top: 16px;
  background: var(--n-border-color);
}

.diff-wrapper {
  flex: 1;
  overflow: auto;
  background: var(--n-color);
  
  &.left {
    border-right: 1px solid var(--n-border-color);
  }
}

.diff-content {
  font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.6;
}

.diff-line {
  display: flex;
  min-height: 24px;
  
  &.line-unchanged {
    background: transparent;
    
    &:hover {
      background: var(--n-color-hover);
    }
  }
  
  &.line-added {
    background: rgba(82, 196, 26, 0.1);
    
    .line-content {
      color: #52c41a;
    }
  }
  
  &.line-deleted {
    background: rgba(245, 34, 45, 0.1);
    
    .line-content {
      color: #f5222d;
    }
  }
  
  &.line-modified {
    background: rgba(250, 173, 20, 0.05);
    transition: background-color 0.2s ease;
    
    &:hover {
      background: rgba(250, 173, 20, 0.1);
    }
    
    .line-content {
      color: inherit; // 保持原色，只通过字符级别高亮显示差异
    }
  }
  
  &.line-empty {
    background: var(--n-color-modal);
  }
}

.line-number {
  width: 50px;
  padding: 2px 8px;
  text-align: right;
  color: var(--n-text-color3);
  background: var(--n-color-modal);
  border-right: 1px solid var(--n-border-color);
  user-select: none;
  flex-shrink: 0;
}

.line-content {
  flex: 1;
  padding: 2px 12px;
  white-space: pre-wrap;
  word-break: break-all;
  
  // 字符级别差异高亮样式
  :deep(.char-deleted) {
    background-color: rgba(255, 59, 48, 0.25);
    text-decoration: line-through;
    color: #d00;
    padding: 2px 3px;
    margin: 0 1px;
    border-radius: 3px;
    border: 1px solid rgba(255, 59, 48, 0.3);
  }
  
  :deep(.char-inserted) {
    background-color: rgba(52, 199, 89, 0.25);
    color: #080;
    padding: 2px 3px;
    margin: 0 1px;
    border-radius: 3px;
    font-weight: 500;
    border: 1px solid rgba(52, 199, 89, 0.3);
  }
}

// 模态框头部样式
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  
  .modal-title {
    font-size: 18px;
    font-weight: 500;
  }
  
  .header-legend {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-left: auto;
    margin-right: 20px;
  }
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  
  .legend-color {
    width: 14px;
    height: 14px;
    border-radius: 3px;
    
    &.unchanged {
      background: transparent;
      border: 1px solid var(--n-border-color);
    }
    
    &.modified {
      background: rgba(250, 173, 20, 0.2);
      border: 1px solid rgba(250, 173, 20, 0.5);
    }
    
    &.added {
      background: rgba(82, 196, 26, 0.3);
      border: 1px solid rgba(82, 196, 26, 0.5);
    }
    
    &.deleted {
      background: rgba(245, 34, 45, 0.3);
      border: 1px solid rgba(245, 34, 45, 0.5);
    }
  }
}

// 移动端适配
@media (max-width: 768px) {
  .modal-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
    
    .header-legend {
      margin-left: 0;
      margin-right: 0;
      width: 100%;
      overflow-x: auto;
      
      .n-space {
        flex-wrap: nowrap;
      }
    }
  }
  
  .legend-item {
    font-size: 12px;
    white-space: nowrap;
  }
  
  .view-header {
    flex-direction: column;
    gap: 8px;
    
    .view-title {
      text-align: center !important;
    }
    
    .vs-divider {
      display: none;
    }
  }
  
  .diff-container {
    flex-direction: column;
  }
  
  .diff-wrapper {
    &.left {
      border-right: none;
      border-bottom: 2px solid var(--n-border-color);
    }
  }
  
  .diff-content {
    font-size: 12px;
  }
  
  .line-number {
    width: 40px;
    padding: 2px 4px;
  }
  
  .line-content {
    padding: 2px 8px;
  }
}

// 滚动条样式
.diff-wrapper {
  &::-webkit-scrollbar {
    width: 8px;
    height: 8px;
  }
  
  &::-webkit-scrollbar-track {
    background: var(--n-color-modal);
  }
  
  &::-webkit-scrollbar-thumb {
    background: var(--n-scrollbar-color);
    border-radius: 4px;
  }
  
  &::-webkit-scrollbar-thumb:hover {
    background: var(--n-scrollbar-color-hover);
  }
}
</style>